#include <iostream>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include "Log.hpp"

using namespace std;

void Usage(string s)
{
    s += " ip port";
    cout << s << endl;
}

// ./tcpclient ip port
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        return 0;
    }

    sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    inet_aton(argv[1], &server.sin_addr);

    uint16_t serverPort = stoi(argv[2]);
    server.sin_port = htons(serverPort);

    while (true)
    {
        // 重连次数
        int cnt = 5;
        bool isreconnect = false;

        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
        {
            lg(Fatal, "client sockfd create fail,errno:%d,message:%s", errno, strerror(errno));
            exit(1);
        }
        lg(Info, "client sockfd create success,sockfd:%d", sockfd);

        do
        {
            // 客户端在connect的时候自动bind，并自动给其分配端口号
            int res = connect(sockfd, (sockaddr *)&server, sizeof(server));
            if (res < 0)
            {
                // lg(Fatal, "client sockfd create fail,errno:%d,message:%s", errno, strerror(errno));
                cout<<"reconnect: "<<cnt<<endl;
                isreconnect = true;
                cnt--;
                sleep(1);
            }
            else
            {
                lg(Info, "client connect create success,sockfd:%d", sockfd);
                break;
            }
        } while (cnt && isreconnect);

        if(cnt == 0)
        {
            cout<<"user offline"<<endl;
            break;
        }

        string message;
        cout << "Client Enter# ";
        getline(cin, message);

        // 考虑如果向服务端写入的时候，服务器直接关了，在循环的开始写一个重连的模块
        int n = write(sockfd, message.c_str(), message.size());
        if (n < 0)
        {
            lg(Warning, "client write to server fail,errno:%d,message:%s", errno, strerror(errno));
            continue;
        }

        char buffer[1024];
        n = read(sockfd, buffer, sizeof(buffer));
        if (n > 0)
        {
            buffer[n] = '\0';
            cout << buffer << endl;
        }
        else
        {
            lg(Info, "client read nothing");
        }

        close(sockfd);
    }

    return 0;
}